home *** CD-ROM | disk | FTP | other *** search
- /*
- * gr2ps - convert a gremlin file into a PostScript printer
- * language file, which can be printed to printers which
- * support PostScript (like the Apple LaserWriter).
- *
- * (c) 1986 John Coker
- * University of California, Berkeley
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <math.h>
- #include <varargs.h>
-
- #define isinteger(c) (isdigit(c) || (c) == '-')
- #define isfloat(c) (isdigit(c) || (c) == '.' || (c) == '-')
-
- char *program;
- char USAGE[] = "usage: %s [ -n ] [ -R font ] [ -I font ] [ -B font ] [ -S font ] [ -s X Y ] [ -t X Y ] [ -p X Y ] [ -o file ] [ file ]\n";
- char *errfile = NULL;
- int errline = -1;
-
- int setscale = 0;
- double gscaleX = 1.0, gscaleY = 1.0;
- int settrans = 0;
- double gtransX = 0.0, gtransY = 0.0;
- int setplace = 0;
- double gplaceX = 0.0, gplaceY = 0.0;
- int newformat = 0;
-
- char *R_fontname = "Times-Roman";
- char *I_fontname = "Times-Italic";
- char *B_fontname = "Times-Bold";
- char *S_fontname = "Courier-Bold";
-
- main(argc, argv)
- char *argv[];
- {
- extern char *rindex();
- extern double atof();
- register char *ap;
- char *outputfile = NULL;
- FILE *input, *output;
- int status;
-
- program = rindex(*argv, '/');
- if (program == NULL)
- program = *argv;
- else
- program++;
-
- /* process command line options */
- while (--argc > 0 && **++argv == '-') {
- if (*(*argv+1) == '\0')
- break;
- for (ap = ++*argv; *ap != '\0'; ap++)
- switch (*ap) {
- case 'B': /* bold font name */
- if (--argc < 1 || *++argv == NULL) {
- fprintf(stderr, USAGE, program);
- exit(1);
- }
- B_fontname = *argv;
- break;
- case 'I': /* italic font name */
- if (--argc < 1 || *++argv == NULL) {
- fprintf(stderr, USAGE, program);
- exit(1);
- }
- I_fontname = *argv;
- break;
- case 'R': /* roman font name */
- if (--argc < 1 || *++argv == NULL) {
- fprintf(stderr, USAGE, program);
- exit(1);
- }
- R_fontname = *argv;
- break;
- case 'S': /* special font name */
- if (--argc < 1 || *++argv == NULL) {
- fprintf(stderr, USAGE, program);
- exit(1);
- }
- S_fontname = *argv;
- break;
- case 'n': /* newer file format */
- newformat = 1;
- break;
- case 'o': /* specity output file */
- if (--argc < 1 || *++argv == NULL) {
- fprintf(stderr, USAGE, program);
- exit(1);
- }
- outputfile = *argv;
- break;
- case 'p': /* place at this position */
- if (argc < 3 || !isfloat(argv[1][0]) ||
- !isfloat(argv[2][0])) {
- fprintf(stderr, USAGE, program);
- exit(1);
- }
- gplaceX = atof(argv[1]);
- gplaceY = atof(argv[2]);
- argc -= 2;
- argv += 2;
- setplace = 1;
- break;
- case 's': /* specify global scale */
- if (argc < 3 || !isfloat(argv[1][0]) ||
- !isfloat(argv[2][0])) {
- fprintf(stderr, USAGE, program);
- exit(1);
- }
- gscaleX = atof(argv[1]);
- gscaleY = atof(argv[2]);
- argc -= 2;
- argv += 2;
- setscale = 1;
- break;
- case 't': /* specify global translation */
- if (argc < 3 || !isfloat(argv[1][0]) ||
- !isfloat(argv[2][0])) {
- fprintf(stderr, USAGE, program);
- exit(1);
- }
- gtransX = atof(argv[1]);
- gtransY = atof(argv[2]);
- argc -= 2;
- argv += 2;
- settrans = 1;
- break;
- default: /* bad option */
- fprintf(stderr, USAGE, program);
- exit(1);
- }
- }
- if (settrans && setplace) {
- fprintf(stderr, "%s: Only one of -t and -p, please.\n",
- program);
- exit(1);
- }
-
- /* open output file */
- if (outputfile == NULL || *outputfile == '\0') {
- /* use standard output */
- output = stdout;
- } else if ((output = fopen(outputfile, "w")) == NULL) {
- fprintf(stderr, "%s: Can't open output file ", program);
- perror(outputfile);
- exit(1);
- }
-
- /* read and translate given gremlin files */
- if (argc > 0) {
- /* loop over argument file names */
- status = 0;
- while (argc-- > 0) {
- if (**argv == '\0' || !strcmp(*argv, "-")) {
- /* read standard input at this point */
- errline = 0;
- errfile = "(stdin)";
- status += grn_to_ps(input, output) != 0;
- } else if ((input = fopen(*argv, "r")) == NULL) {
- fprintf(stderr, "%s: Can't open ", program);
- perror(*argv);
- status++;
- } else {
- errline = 0;
- errfile = *argv;
- status += grn_to_ps(input, output) != 0;
- fclose(input);
- }
- argv++;
- }
- } else {
- /* process standard input */
- errline = 0;
- errfile = "(stdin)";
- status = grn_to_ps(stdin, output) != 0;
- }
-
- if (output != stdout)
- fclose(output);
-
- exit(0);
- }
-
- char OLDFIRSTLINE[] = "gremlinfile\n";
- char NEWFIRSTLINE[] = "sungremlinfile\n";
- int LASTELEMENT = -1;
-
- static char *element_names[] = {
- "BOTLEFT", /* bottom left text - 0 */
- "BOTRIGHT", /* bottom right text - 1 */
- "CENTCENT", /* center text - 2 */
- "VECTOR", /* vector - 3 */
- "ARC", /* arc - 4 */
- "CURVE", /* curve - 5 */
- "POLYGON", /* polygon - 6 */
- "CURVE BSPLINE", /* b-spline - 7 */
- "CURVE BEZIER", /* bezier spline - 8 */
- NULL,
- "TOPLEFT", /* top left text - 10 */
- "TOPCENT", /* top center text - 11 */
- "TOPRIGHT", /* top right text - 12 */
- "CENTLEFT", /* left center text - 13 */
- "CENTRIGHT", /* right center text - 14 */
- "BOTCENT", /* bottom center text - 15 */
- };
- static int element_count = sizeof (element_names) / sizeof (char *);
-
- struct point {
- double p_x,
- p_y;
- };
-
- struct element {
- short e_what; /* what type of element */
- short e_ptcnt; /* number of points */
- struct point *e_points; /* list of points */
- short e_brush; /* brush style */
- short e_size; /* text size */
- char *e_text; /* text string */
- double e_llx, /* lower-left X */
- e_lly, /* lower-left Y */
- e_urx, /* upper-right X */
- e_ury; /* upper-right Y */
- };
-
- #define MAXPOINTS 500 /* maximum points per element */
- #define MAXELEMENTS 5000 /* maximum elements per file */
-
- #define TOP 1 /* top oriented text */
- #define BOTTOM 2 /* bottom oriented text */
- #define LEFT 3 /* left justified text */
- #define CENTER 4 /* centered text */
- #define RIGHT 5 /* right justified text */
-
- #define LARGE 1000000 /* initial value for max/min pairs */
-
- /* these should be local variables, but ... */
- static struct element elt_list[MAXELEMENTS];
- static struct point point_list[MAXPOINTS];
-
- grn_to_ps(input, output)
- FILE *input, *output;
- {
- extern double atof();
- extern char *malloc(), *savestr();
- char lbuf[1024];
- register char *lp, *ep;
- struct point *point_end = point_list + MAXPOINTS;
- struct point *ptp, *ptend;
- struct element *elt_end = elt_list + MAXELEMENTS;
- struct element *elt, *elend;
- register int e, t, len;
- double llx, lly, urx, ury;
-
- /* check validity of this file */
- if (fgets(lbuf, sizeof (lbuf), input) == NULL) {
- error("Input file is empty!");
- return (-1);
- }
- errline = 1;
- if (strcmp(lbuf, NEWFIRSTLINE) == 0) {
- /* this is new format, at least */
- newformat = 1;
- } else if (strcmp(lbuf, OLDFIRSTLINE) != 0) {
- error("Input file not produced by gremlin!");
- return (-1);
- }
-
- /* get orientation/positioning line */
- if (fgets(lbuf, sizeof (lbuf), input) == NULL) {
- error("Input file is too short (missing orientation).");
- return (-1);
- }
- errline++;
-
- /* initialize bounding box values */
- llx = lly = LARGE;
- urx = ury = -LARGE;
-
- /* look through file reading picture elements */
- elt = elt_list;
- while (fgets(lbuf, sizeof (lbuf), input) != NULL && elt < elt_end) {
- errline++;
- /* read in this element specification */
- for (lp = lbuf; isspace(*lp); lp++)
- ;
- if (newformat && !isinteger(*lp)) {
- for (ep = lp; *ep != '\0' && *ep != '\n'; ep++)
- ;
- do
- *ep-- = '\0';
- while (ep > lp && isspace(*ep));
- if (ep <= lp) {
- error("Missing element name!");
- return (-1);
- }
- for (e = 0; e < element_count; e++)
- if (element_names[e] != NULL &&
- !strcmp(element_names[e], lp))
- break;
- if (e >= element_count) {
- error("Unknown element type %s!", lp);
- return (1);
- }
- elt->e_what = e;
- } else if (isinteger(*lp)) {
- /* old style numeric element type */
- elt->e_what = atoi(lbuf);
- } else {
- error("Bad format for element specification.");
- return (-1);
- }
- if (elt->e_what == LASTELEMENT) {
- /* this is the end-of-list marker */
- break;
- }
-
- /* read in associated point list */
- ptend = point_list;
- while (fgets(lbuf, sizeof (lbuf), input) != NULL &&
- ptend < point_end) {
- errline++;
- /* read in this X and Y coordinate */
- for (lp = lbuf; isspace(*lp); lp++)
- ;
- if (newformat && *lp == '*')
- break;
- if (!isfloat(*lp))
- goto badpoint;
- ptend->p_x = atof(lp);
- while (isfloat(*lp))
- lp++;
- while (isspace(*lp))
- lp++;
- if (!isfloat(*lp)) {
- badpoint: error("Bad point specified, need X and Y.");
- return (-1);
- }
- ptend->p_y = atof(lp);
- if (!newformat &&
- ptend->p_x < 0.0 && ptend->p_y < 0.0) {
- /* end of point list */
- break;
- }
- ptend++;
- }
- if (ptend >= point_end) {
- error("Too many points, maximum is %d!", MAXPOINTS);
- return (-1);
- }
-
- /* read brush and size specification */
- if (fgets(lbuf, sizeof (lbuf), input) == NULL) {
- error("File too short (no brush/size entry)!");
- return (-1);
- }
- errline++;
- for (lp = lbuf; isspace(*lp); lp++)
- ;
- if (!isdigit(*lp)) {
- error("Missing brush value for entry!");
- return (-1);
- }
- elt->e_brush = atoi(lp);
- while (isdigit(*lp))
- lp++;
- while (isspace(*lp))
- lp++;
- if (!isdigit(*lp)) {
- error("Missing size value for entry!");
- return (-1);
- }
- elt->e_size = atoi(lp);
-
- /* read count/text specification */
- if (fgets(lbuf, sizeof (lbuf), input) == NULL) {
- error("File too short (missing text entry)!");
- return (-1);
- }
- errline++;
- for (lp = lbuf; isspace(*lp); lp++)
- ;
- if (!isdigit(*lp)) {
- error("Missing text length value in entry!");
- return (-1);
- }
- len = atoi(lp);
- if (len <= 0) {
- /* no text string */
- elt->e_text = NULL;
- } else {
- char *text;
-
- while (isdigit(*lp))
- lp++;
- while (isspace(*lp))
- lp++;
- text = lp;
- for (t = 0; t < len && *lp != '\n'; t++)
- lp++;
- if (t < len) {
- #ifdef NOTDEF
- error("Text not as long as length given!");
- /*
- * There's a bug in gremlin that sometimes gives a bogus text length if
- * the text itself is a string of digits. But nothing goes wrong if you
- * ignore the given length here.
- */
- return(1);
- #else
- error("Text not as long as length given, but this is probably okay");
- #endif /* NOTDEF */
- }
- *lp = '\0';
- elt->e_text = savestr(text);
- }
-
- /* add this picture element to list */
- elt->e_ptcnt = ptend - point_list;
- if (elt->e_ptcnt > 0) {
- elt->e_points = (struct point *)
- malloc(elt->e_ptcnt * sizeof (struct point));
- if (elt->e_points == NULL) {
- fprintf(stderr,
- "%s: Not enough memory to save %d points!\n",
- program, elt->e_ptcnt);
- return (-1);
- }
- bcopy((char *)point_list, (char *)elt->e_points,
- elt->e_ptcnt * sizeof (struct point));
- }
-
- /* scale and translate the elements */
- if (setscale)
- scale(elt, gscaleX, gscaleY);
- if (settrans)
- translate(elt, gtransX, gtransY);
-
- /* save the bounding box information */
- findbbox(elt);
- if (elt->e_llx < llx)
- llx = elt->e_llx;
- if (elt->e_lly < lly)
- lly = elt->e_lly;
- if (elt->e_urx > urx)
- urx = elt->e_urx;
- if (elt->e_ury > ury)
- ury = elt->e_ury;
-
- /* on to the next element ... */
- elt++;
- }
- elend = elt;
-
- /* handle placing the figure */
- if (setplace) {
- double dx, dy;
-
- dx = gplaceX - llx;
- dy = gplaceY - lly;
-
- /* move the individual elements */
- for (elt = elt_list; elt < elend; elt++)
- translate(elt, dx, dy);
-
- /* update the entire bounding box */
- llx += dx;
- lly += dy;
- urx += dx;
- ury += dy;
- }
-
- /* output the header comments */
- fprintf(output, "%%!\n");
- fprintf(output, "%%%%Title: %s\n", errfile);
- fprintf(output, "%%%%Creator: %s (Gremlin to PostScript)\n", program);
- fprintf(output, "%%%%BoundingBox: %lg %lg %lg %lg\n",
- llx, lly, urx, ury);
- fprintf(output, "%%%%DocumentFonts: %s %s %s %s\n",
- R_fontname, I_fontname, B_fontname, S_fontname);
- fprintf(output, "%%%%Pages: 1\n");
- fprintf(output, "%%%%EndComments\n\n");
-
- /* output the prologue code */
- fprintf(output, "gsave\n");
- fprintf(output, "%%%%EndProlog\n");
-
- /* Output polygons first, text second and lines last to keep one
- object from covering another as much as possible. */
- for (elt = elt_list; elt < elend; elt++) {
- /* handle this picture element now */
- putc('\n', output);
- switch (elt->e_what) {
- case 6: /* polygon */
- if (elt->e_ptcnt < 3) {
- error("Need three or more points in polygon.");
- return (1);
- }
- polystyle(elt->e_brush, elt->e_size, output);
- makepolygon(elt->e_ptcnt, elt->e_points, output,
- elt->e_brush, elt->e_size);
- break;
- }
- if (elt->e_what > 15) {
- error("Bad element type %d; ignored.", elt->e_what);
- }
- }
- for (elt = elt_list; elt < elend; elt++) {
- /* handle this picture element now */
- putc('\n', output);
- switch (elt->e_what) {
- case 0: /* bottom-left justified text */
- textstyle(elt->e_brush, elt->e_size, output);
- textpoint(elt->e_ptcnt, elt->e_points, output);
- textadjust(elt->e_text, BOTTOM, LEFT, output);
- break;
- case 1: /* bottom-right justified text */
- textstyle(elt->e_brush, elt->e_size, output);
- textpoint(elt->e_ptcnt, elt->e_points, output);
- textadjust(elt->e_text, BOTTOM, RIGHT, output);
- break;
- case 2: /* center justified text */
- textstyle(elt->e_brush, elt->e_size, output);
- textpoint(elt->e_ptcnt, elt->e_points, output);
- textadjust(elt->e_text, CENTER, CENTER, output);
- break;
- case 10: /* top-left justified text */
- textstyle(elt->e_brush, elt->e_size, output);
- textpoint(elt->e_ptcnt, elt->e_points, output);
- textadjust(elt->e_text, TOP, LEFT, output);
- break;
- case 11: /* top-center justified text */
- textstyle(elt->e_brush, elt->e_size, output);
- textpoint(elt->e_ptcnt, elt->e_points, output);
- textadjust(elt->e_text, TOP, CENTER, output);
- break;
- case 12: /* top-right justified text */
- textstyle(elt->e_brush, elt->e_size, output);
- textpoint(elt->e_ptcnt, elt->e_points, output);
- textadjust(elt->e_text, TOP, RIGHT, output);
- break;
- case 13: /* left-center justified text */
- textstyle(elt->e_brush, elt->e_size, output);
- textpoint(elt->e_ptcnt, elt->e_points, output);
- textadjust(elt->e_text, CENTER, LEFT, output);
- break;
- case 14: /* right-center justified text */
- textstyle(elt->e_brush, elt->e_size, output);
- textpoint(elt->e_ptcnt, elt->e_points, output);
- textadjust(elt->e_text, CENTER, RIGHT, output);
- break;
- case 15: /* bottom-center justified text */
- textstyle(elt->e_brush, elt->e_size, output);
- textpoint(elt->e_ptcnt, elt->e_points, output);
- textadjust(elt->e_text, BOTTOM, CENTER, output);
- break;
- }
- if (elt->e_what > 15) {
- error("Bad element type %d; ignored.", elt->e_what);
- }
- }
- for (elt = elt_list; elt < elend; elt++) {
- /* handle this picture element now */
- putc('\n', output);
- switch (elt->e_what) {
- case 3: /* vector */
- if (elt->e_ptcnt < 2) {
- error("Need at least two points in a vector.");
- break;
- }
- linestyle(elt->e_brush, elt->e_size, output);
- ptp = point_list;
- makevector(elt->e_ptcnt, elt->e_points, output);
- break;
- case 4: /* arc */
- if (elt->e_ptcnt < 2) {
- error("Need at least two points for an arc!");
- return (1);
- }
- linestyle(elt->e_brush, elt->e_size, output);
- makearc(elt->e_ptcnt, elt->e_points, output);
- break;
- case 5: /* curve */
- if (elt->e_ptcnt < 3) {
- error("Need at least three points for curve.");
- return (1);
- }
- linestyle(elt->e_brush, elt->e_size, output);
- makecurve(elt->e_ptcnt, elt->e_points, output);
- break;
- case 7: /* b-spline curve */
- if (elt->e_ptcnt < 2) {
- error(
- "Can't draw B-spline with fewer than two points.");
- return (1);
- }
- linestyle(elt->e_brush, elt->e_size, output);
- makebspline(elt->e_ptcnt, elt->e_points, output);
- break;
- case 8: /* bezier spline curve */
- if (elt->e_ptcnt < 3) {
- error(
- "Can't draw Bezier with fewer than two points.");
- return (1);
- }
- linestyle(elt->e_brush, elt->e_size, output);
- makebezier(elt->e_ptcnt, elt->e_points, output);
- break;
- }
- if (elt->e_what > 15) {
- error("Bad element type %d; ignored.", elt->e_what);
- }
- }
-
- /* terminate the page description with trailer */
- fprintf(output, "\n%%%%Trailer\n");
- fprintf(output, "grestore\n");
-
- return (0);
- }
-
- findbbox(elt)
- struct element *elt;
- {
- struct point *ptp, *end;
- double minx, maxx, miny, maxy;
-
- /* initialize bounding box values */
- minx = miny = LARGE;
- maxx = maxy = -LARGE;
-
- end = elt->e_points + elt->e_ptcnt;
- for (ptp = elt->e_points; ptp < end; ptp++) {
- if (ptp->p_x < minx)
- minx = ptp->p_x;
- if (ptp->p_x > maxx)
- maxx = ptp->p_x;
- if (ptp->p_y < miny)
- miny = ptp->p_y;
- if (ptp->p_y > maxy)
- maxy = ptp->p_y;
- }
-
- /* make sure we have a reaonable bounding box */
- if (minx > maxx || miny > maxy)
- minx = maxx = miny = maxy = 0.0;
-
- /* set them in the element and return */
- elt->e_llx = minx;
- elt->e_lly = miny;
- elt->e_urx = maxx;
- elt->e_ury = maxy;
- return (0);
- }
-
- scale(elt, xscale, yscale)
- struct element *elt;
- double xscale, yscale;
- {
- struct point *ptp, *end;
-
- end = elt->e_points + elt->e_ptcnt;
- for (ptp = elt->e_points; ptp < end; ptp++) {
- ptp->p_x *= xscale;
- ptp->p_y *= yscale;
- }
- /* find bounding box now that it's changed */
- return findbbox(elt);
- }
-
- translate(elt, xtrans, ytrans)
- struct element *elt;
- double xtrans, ytrans;
- {
- struct point *ptp, *end;
-
- end = elt->e_points + elt->e_ptcnt;
- for (ptp = elt->e_points; ptp < end; ptp++) {
- ptp->p_x += xtrans;
- ptp->p_y += ytrans;
- }
-
- /* adjust bounding box by translation */
- elt->e_llx += xtrans;
- elt->e_lly += ytrans;
- elt->e_urx += xtrans;
- elt->e_ury += ytrans;
- return (0);
- }
-
- double curgray = 0.0;
- int dashset = 0;
- double curwidth = -1.0;
-
- #define THINWIDTH 0.3
- #define MEDWIDTH 0.8
- #define THICKWIDTH 1.4
-
- linestyle(brush, size, output)
- FILE *output;
- {
- /* set up line style (or brush) approriately */
- switch (brush) {
- case 1: /* thin dotted lines */
- fputs("[1.0 1.6] 0 setdash\n", output);
- dashset = 1;
- if (curwidth != THINWIDTH) {
- curwidth = THINWIDTH;
- fprintf(output, "%lg setlinewidth\n", curwidth);
- }
- break;
- case 2: /* thin dot-dashed lines */
- fputs("[1.0 1.6 3.5 1.6] 0 setdash ", output);
- dashset = 1;
- if (curwidth != THINWIDTH) {
- curwidth = THINWIDTH;
- fprintf(output, "%lg setlinewidth\n", curwidth);
- }
- break;
- case 3: /* thick solid lines */
- if (dashset) {
- fputs("[] 0 setdash ", output);
- dashset = 0;
- }
- if (curwidth != THICKWIDTH) {
- curwidth = THICKWIDTH;
- fprintf(output, "%lg setlinewidth\n", curwidth);
- }
- break;
- case 4: /* thin dashed lines */
- fputs("[3.5 3.0] 0 setdash ", output);
- dashset = 1;
- if (curwidth != THINWIDTH) {
- curwidth = THINWIDTH;
- fprintf(output, "%lg setlinewidth\n", curwidth);
- }
- break;
- case 5: /* thin solid lines */
- if (dashset) {
- fputs("[] 0 setdash ", output);
- dashset = 0;
- }
- if (curwidth != THINWIDTH) {
- curwidth = THINWIDTH;
- fprintf(output, "%lg setlinewidth\n", curwidth);
- }
- break;
- case 6: /* medium solid lines */
- if (dashset) {
- fputs("[] 0 setdash ", output);
- dashset = 0;
- }
- if (curwidth != MEDWIDTH) {
- curwidth = MEDWIDTH;
- fprintf(output, "%lg setlinewidth\n", curwidth);
- }
- break;
- default: /* bad brush type */
- error("Bad brush type %d specified; ignored.", brush);
- return (1);
- }
-
- /* lines are always drawn full strength */
- if (curgray != 0.0) {
- curgray = 0.0;
- fprintf(output, "%lg setgray\n", curgray);
- }
-
- /* size is ignored for vectors, arcs and curves */
-
- return (0);
- }
-
- #define BLACK 16
- #define WHITE 1
-
- polystyle(brush, size, output)
- FILE *output;
- {
- double level, steps;
-
- /* ignore outline style (or brush) here */
-
- /* size is stipple pattern index */
- if (size > BLACK)
- size = BLACK;
- if (size < WHITE)
- size = WHITE;
- steps = 100.0 / (double)BLACK;
- level = 100.0 - (steps * (size - 1));
- if (level != curgray) {
- fprintf(output, "%lg setgray\n", level / 100.0);
- curgray = level;
- }
-
- return (0);
- }
-
- textpoint(count, list, output)
- struct point *list;
- FILE *output;
- {
- double x, y;
- register int i;
-
- if (count < 1) {
- error("Need at least one point for text items!");
- return (-1);
- }
- #ifdef STUPID
- x = y = 0.0;
- for (i = 0; i < count; i++) {
- x += list[i].p_x;
- y += list[i].p_y;
- }
- x = x / (double)count;
- y = y / (double)count;
- #else !STUPID
- x = list[0].p_x;
- y = list[0].p_y;
- #endif STUPID
-
- fprintf(output, "%lg %lg moveto\n", x, y);
- return(0);
- }
-
- char *curfont = NULL;
- int cursize = -1;
-
- textstyle(brush, size, output)
- FILE *output;
- {
- char *fname;
- int fsize;
-
- /* set the font face from brush */
- switch (brush) {
- default: /* unknown face */
- error("Bad font number %d in entry; using Roman.", brush);
- /* fall through ... */
- case 1: /* roman */
- fname = R_fontname;
- break;
- case 2: /* italics */
- fname = I_fontname;
- break;
- case 3: /* bold */
- fname = B_fontname;
- break;
- case 4: /* special */
- fname = S_fontname;
- break;
- }
-
- /* set point size from the size entry */
- switch (size) {
- case 1: /* 8 point */
- fsize = 8;
- break;
- case 2: /* 12 point */
- fsize = 12;
- break;
- case 3: /* 18 point */
- fsize = 18;
- break;
- case 4: /* 28 point */
- fsize = 28;
- break;
- default:
- error("Bad font size %d; using eight point.", size);
- fsize = 8;
- break;
- }
-
- /* text is always printed full strength */
- if (curgray != 0.0) {
- fputs("0 setgray\n", output);
- curgray = 0.0;
- }
-
- /* get font at given size if not already done */
- if (fname != curfont || fsize != cursize) {
- fprintf(output,
- "/%s findfont %d scalefont setfont\n", fname, fsize);
- curfont = fname;
- cursize = fsize;
- }
-
- return (0);
- }
-
- textadjust(text, vert, hor, output)
- char *text;
- FILE *output;
- {
- char sbuf[BUFSIZ], *send = sbuf + sizeof (sbuf) - 1;
- register char *tp, *sp;
- double vmove;
-
- if (text == NULL || *text == '\0') {
- error("Null text string to show!");
- return (-1);
- }
- tp = text;
- sp = sbuf;
- while (*tp != '\0' && sp < send) {
- switch (*tp) {
- case '(':
- case ')':
- case '\\':
- *sp++ = '\\';
- *sp++ = *tp++;
- break;
- default:
- *sp++ = *tp++;
- break;
- }
- }
- *sp = '\0';
-
- /* make adjustment movements, we try to do this optimally ... */
- switch (vert) {
- case BOTTOM:
- vmove = 1.0;
- break;
- case CENTER:
- vmove = 1.0 - (double)cursize / 2.0;
- break;
- case TOP:
- vmove = 1.0 - (double)cursize;
- break;
- }
-
- switch (hor) {
- case LEFT:
- if (vmove != 0.0)
- fprintf(output, "0 %lg rmoveto ", vmove);
- fprintf(output, "(%s) show\n", sbuf);
- break;
- case CENTER:
- fprintf(output,
- "(%s) dup stringwidth pop 2.0 div -1 mul %lg rmoveto show\n",
- sbuf, vmove);
- break;
- case RIGHT:
- fprintf(output,
- "(%s) dup stringwidth pop -1 mul %lg rmoveto show\n",
- sbuf, vmove);
- break;
- }
-
- return (0);
- }
-
- makevector(count, list, output)
- struct point *list;
- FILE *output;
- {
- struct point *ptp, *ptend;
-
- if (list == NULL || count < 2)
- return (1);
-
- ptend = list + count;
- ptp = list;
-
- fprintf(output, "newpath\n %lg %lg moveto\n",
- ptp->p_x, ptp->p_y);
- for (++ptp; ptp < ptend; ptp++)
- fprintf(output, " %lg %lg lineto\n",
- ptp->p_x, ptp->p_y);
- fputs("stroke\n", output);
-
- return (0);
- }
-
- makepolygon(count, list, output, brush, size)
- struct point *list;
- FILE *output;
- {
- struct point *ptp, *ptend;
-
- if (list == NULL || count < 3)
- return (1);
-
- ptp = list;
- ptend = list + count;
-
- /* output the filled region now */
- fprintf(output, "newpath\n %lg %lg moveto\n",
- ptp->p_x, ptp->p_y);
- for (++ptp; ptp < ptend; ptp++) {
- fprintf(output, " %lg %lg lineto\n",
- ptp->p_x, ptp->p_y);
- }
- fputs("closepath fill\n", output);
-
- /* draw the outline now, unless brush is zero */
- if (brush > 0) {
- linestyle(brush, size, output);
- ptp = list;
- fprintf(output, "newpath\n %lg %lg moveto\n",
- ptp->p_x, ptp->p_y);
- for (++ptp; ptp < ptend; ptp++)
- fprintf(output, " %lg %lg lineto\n",
- ptp->p_x, ptp->p_y);
- fputs("closepath stroke\n", output);
- }
-
- return (0);
- }
-
- #define sqr(x) ((x) * (x))
- #define TWOPI (2.0 * 3.1415927)
-
- makearc(count, list, output)
- struct point *list;
- FILE *output;
- {
- double ang1, ang2, radius;
- double dx, dy;
-
- /* get radius from center of curvature and a point */
- radius = hypot(list[0].p_x - list[1].p_x, list[0].p_y - list[1].p_y);
-
- fputs("newpath ", output);
- if (count == 2 || count == 6 ||
- (list[1].p_x == list[2].p_x && list[1].p_y == list[2].p_y)) {
- /* drawing a circle, don't need angles */
- fprintf(output, "%lg %lg %lg 0 360 arc",
- list[0].p_x, list[0].p_y, radius);
- } else {
- /* drawing an arc, find two angles */
- dx = list[1].p_x - list[0].p_x;
- dy = list[1].p_y - list[0].p_y;
- ang1 = atan2(dy, dx) / TWOPI * 360.0;
- dx = list[2].p_x - list[0].p_x;
- dy = list[2].p_y - list[0].p_y;
- ang2 = atan2(dy, dx) / TWOPI * 360.0;
- /* output proper PostScript code */
- fprintf(output, "%lg %lg %lg %lg %lg arc",
- list[0].p_x, list[0].p_y, radius, ang1, ang2);
- }
- fputs(" stroke\n", output);
-
- return (0);
- }
-
- error(va_alist)
- va_dcl
- {
- char *format;
- va_list args;
-
- va_start(args);
- format = va_arg(args, char *);
-
- fprintf(stderr, "%s: \"%s\", %d: ", program, errfile, errline);
- vfprintf(stderr, format, args);
- putc('\n', stderr);
- }
-
- char *
- savestr(str)
- char *str;
- {
- extern char *malloc();
- char *ptr;
- int len;
-
- if (*str == NULL || (len = strlen(str)) < 1)
- return (NULL);
- if ((ptr = malloc(len + 1)) == NULL) {
- fprintf(stderr, "%s: Not enough memory for %d char. string!\n",
- program, len);
- exit(1);
- }
- strcpy(ptr, str);
- return (ptr);
- }
-